package com.socket.client;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

public class ClientActionController {

	ObjectInputStream ois;
	ObjectOutputStream oos;
	Map<String, Object> mReceivedMap;
	// 储存上一次获得的正确的map信息，以便当接受的不是自己想要的时候，恢复用.在异常捕获后重发使用
	Map<String, Object> lastCorrectReceivedMap;

	Map<String, Object> sendMap;

	private SplitedFile file;

	private long startOff = -1;
	private SplitedFile.SplitedBytes splitedBytes;

	ClientActionController(Socket s) {
		try {
			oos = new ObjectOutputStream(s.getOutputStream());

			ois = new ObjectInputStream(s.getInputStream());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 正常情况
	 * 
	 * @throws SocketException
	 */
	public boolean receiveAction() throws SocketException {
		Map<String, Object> receivedMap = null;
		try {
			try {
				receivedMap = (Map<String, Object>) ois.readObject();
			} catch (ClassNotFoundException | IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return receiveAction(receivedMap);
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			throw e;
		}
	}

	/**
	 * 情况
	 * 
	 * @throws SocketException
	 */
	public boolean receiveActionAfterError() throws SocketException {
		try {
			return receiveAction(lastCorrectReceivedMap);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			throw new SocketException("没读出来");
		}
	}

	/**
	 * 
	 * @return 下次应该接收的
	 * @throws SocketException
	 * 
	 */
	private boolean receiveAction(Map<String, Object> receivedMap)
			throws SocketException {
		boolean isEnd = false;
		mReceivedMap = receivedMap;
		// 检验是不正确
		getNeedStringValue(Constants.MapKey.STATUS, Constants.STATUS.STATUS_OK);
		// 比对是不是想得到的action
		int action = getIntValue(Constants.MapKey.ACTION);

		switch (action) {
		case Constants.Action.RECEIVE_FILE_START_OFF_NEED:
			isEnd = receiveFileStartOffNeed();
			break;
		case Constants.Action.RECEIVE_FILE_HEAD_INFO_BACK:
			receiveFileHeadInfoBack();
			break;
		case Constants.Action.RECEIVE_FILE:
			break;
		}

		sendAction();

		lastCorrectReceivedMap = mReceivedMap;
		return isEnd;
	}

	private byte[] getBytesValue() throws SocketException {
		try {
			return (byte[]) mReceivedMap
					.get(Constants.MapKey.SPLETED_FILE_BYTES);
		} catch (Exception e) {
			throw new SocketException("提取bytes[]转换错误");
		}
	}

	private boolean getBooleanValue() throws SocketException {
		try {
			return (boolean) mReceivedMap.get(Constants.MapKey.IS_END);
		} catch (Exception e) {
			throw new SocketException("提取isEnd(boolean)转换错误");
		}
	}

	private long getLongValue(String key) throws SocketException {
		try {
			return Long.parseLong(mReceivedMap.get(key).toString());
		} catch (Exception e) {
			throw new SocketException("提取long转换错误key=" + key);
		}
	}

	private int getIntValue(String key) throws SocketException {
		try {
			return Integer.parseInt(mReceivedMap.get(key).toString());
		} catch (Exception e) {
			throw new SocketException("提取int转换错误key=" + key);
		}
	}

	private String getStringValue(String key) throws SocketException {
		String value = (String) mReceivedMap.get(key);
		if (value == null) {
			throw new SocketException("取值错误key=" + key);
		}
		return value;
	}

	private String getNeedStringValue(String key, String needValue)
			throws SocketException {
		String value = getStringValue(key);
		if (!needValue.equals(value)) {
			throw new SocketException("得到的不是想要的key=" + key + " value=" + value
					+ " needValue=" + needValue);
		}
		return value;
	}

	private boolean receiveFileStartOffNeed() throws SocketException {
		boolean isEnd = false;
		isEnd = getBooleanValue();
		if (!isEnd) {
			startOff = getLongValue(Constants.MapKey.START_OFF);
			splitedBytes = file.getBytes(startOff);

			sendMap = new HashMap<String, Object>();
			sendMap.put(Constants.MapKey.STATUS, Constants.STATUS.STATUS_OK);
			// 客户端 action是
			sendMap.put(Constants.MapKey.ACTION,
					Constants.Action.RECEIVE_FILE_HEAD_INFO);
			sendMap.put(Constants.MapKey.START_OFF, startOff);
			sendMap.put(Constants.MapKey.SPLETED_FILE_LENGTH,
					splitedBytes.length);
		}
		return isEnd;
	}

	private void receiveFileHeadInfoBack() throws SocketException {

		sendMap = new HashMap<String, Object>();
		sendMap.put(Constants.MapKey.STATUS, Constants.STATUS.STATUS_OK);
		// 客户端 action是
		sendMap.put(Constants.MapKey.ACTION, Constants.Action.RECEIVE_FILE);
		sendMap.put(Constants.MapKey.SPLETED_FILE_BYTES, splitedBytes.bytes);

	}

	private void sendAction() throws SocketException {
		try {
			oos.writeObject(sendMap);
			oos.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			throw new SocketException("发送错误action="
					+ sendMap.get(Constants.MapKey.ACTION).toString());
		}
	}

	public void sendHeadInfo(String filePath) throws SocketException {
		try {
			file = new SplitedFile(filePath);
			sendMap = new HashMap<String, Object>();
			sendMap.put(Constants.MapKey.STATUS, Constants.STATUS.STATUS_OK);
			sendMap.put(Constants.MapKey.ACTION,
					Constants.Action.RECEIVE_HEAD_INFO);
			sendMap.put(Constants.MapKey.FILE_LENGTH, file.getFileLength());
			sendMap.put(Constants.MapKey.FILE_NAME,
					filePath.substring(Constants.FILE_DIR.length()));
			sendAction();
		} catch (FileNotFoundException e) {
			throw new SocketException("开始发送失败");
		}

	}

	public void close() {
		try {
			oos.close();
			ois.close();
			file.close();
		} catch (IOException e) {
			System.out.println("关闭出错");
		}
	}
}
